gdk: Add gdk_cursor_new_from_surface
authorAlexander Larsson <alexl@redhat.com>
Wed, 7 Aug 2013 10:18:38 +0000 (12:18 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 7 Aug 2013 11:34:10 +0000 (13:34 +0200)
We need this to be able to handle scaled cursor images.
We implement the new _from_pixbuf by converting to a surface and
assuming the scale was 1.

13 files changed:
gdk/broadway/gdkcursor-broadway.c
gdk/broadway/gdkdisplay-broadway.c
gdk/broadway/gdkprivate-broadway.h
gdk/gdkcursor.c
gdk/gdkcursor.h
gdk/gdkdisplayprivate.h
gdk/wayland/gdkcursor-wayland.c
gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkprivate-wayland.h
gdk/x11/gdkcursor-x11.c
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkprivate-x11.h

index 72fc84e1e25d8b371df792a70e12e7a111c6bdfb..dccccc63f86e173211e7c63ca32d671f9ae79f01 100644 (file)
@@ -118,10 +118,10 @@ _gdk_broadway_cursor_update_theme (GdkCursor *cursor)
 }
 
 GdkCursor *
-_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                            GdkPixbuf  *pixbuf,
-                                            gint        x,
-                                            gint        y)
+_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
+                                             cairo_surface_t *surface,
+                                             gdouble     x,
+                                             gdouble     y)
 {
   GdkBroadwayCursor *private;
   GdkCursor *cursor;
index dff7457147e91dbe5fb2ffbfdca3aeec55766d71..36ce56921d46e5d395ef80d13b84debdf7d14640 100644 (file)
@@ -375,7 +375,7 @@ gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
   display_class->list_devices = gdk_broadway_display_list_devices;
   display_class->get_cursor_for_type = _gdk_broadway_display_get_cursor_for_type;
   display_class->get_cursor_for_name = _gdk_broadway_display_get_cursor_for_name;
-  display_class->get_cursor_for_pixbuf = _gdk_broadway_display_get_cursor_for_pixbuf;
+  display_class->get_cursor_for_surface = _gdk_broadway_display_get_cursor_for_surface;
   display_class->get_default_cursor_size = _gdk_broadway_display_get_default_cursor_size;
   display_class->get_maximal_cursor_size = _gdk_broadway_display_get_maximal_cursor_size;
   display_class->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha;
index acbd8a281f320c3923adf18b9cebb2630c8cd030..efc66c0bcb794def2bca5a61199fff4b9a53bc1c 100644 (file)
@@ -125,10 +125,10 @@ GdkCursor*_gdk_broadway_display_get_cursor_for_type (GdkDisplay    *display,
                                                     GdkCursorType  cursor_type);
 GdkCursor*_gdk_broadway_display_get_cursor_for_name (GdkDisplay  *display,
                                                     const gchar *name);
-GdkCursor *_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                                       GdkPixbuf  *pixbuf,
-                                                       gint        x,
-                                                       gint        y);
+GdkCursor *_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display,
+                                                        cairo_surface_t *surface,
+                                                        gdouble     x,
+                                                        gdouble     y);
 gboolean _gdk_broadway_display_supports_cursor_alpha (GdkDisplay *display);
 gboolean _gdk_broadway_display_supports_cursor_color (GdkDisplay *display);
 void _gdk_broadway_display_get_default_cursor_size (GdkDisplay *display,
index d1825913d672eb3064bd457662b9ceba8c084858..a336ea79ef03168387397482866cde7966e682bf 100644 (file)
@@ -34,6 +34,7 @@
 #include "gdkinternals.h"
 
 #include <math.h>
+#include <errno.h>
 
 /**
  * SECTION:cursors
@@ -351,12 +352,81 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display,
                             gint        x,
                             gint        y)
 {
+  cairo_surface_t *surface;
+  const char *option;
+  char *end;
+  gint64 value;
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
   g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
 
-  return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_pixbuf (display, pixbuf, x, y);
+  if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot")))
+    {
+      errno = 0;
+      end = NULL;
+      value = g_ascii_strtoll (option, &end, 10);
+      if (errno == 0 &&
+          end != option &&
+          value >= 0 && value < G_MAXINT)
+        x = (gint) value;
+    }
+  
+  if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot")))
+    {
+      errno = 0;
+      end = NULL;
+      value = g_ascii_strtoll (option, &end, 10);
+      if (errno == 0 &&
+          end != option &&
+          value >= 0 && value < G_MAXINT)
+        y = (gint) value;
+    }
+
+  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
+  
+  return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display, surface, x, y);
 }
 
+/**
+ * gdk_cursor_new_from_surface:
+ * @display: the #GdkDisplay for which the cursor will be created
+ * @surface: the cairo image surface containing the cursor pixel data
+ * @x: the horizontal offset of the 'hotspot' of the cursor.
+ * @y: the vertical offset of the 'hotspot' of the cursor.
+ *
+ * Creates a new cursor from a pixbuf.
+ *
+ * Not all GDK backends support RGBA cursors. If they are not
+ * supported, a monochrome approximation will be displayed.
+ * The functions gdk_display_supports_cursor_alpha() and
+ * gdk_display_supports_cursor_color() can be used to determine
+ * whether RGBA cursors are supported;
+ * gdk_display_get_default_cursor_size() and
+ * gdk_display_get_maximal_cursor_size() give information about
+ * cursor sizes.
+ *
+ * On the X backend, support for RGBA cursors requires a
+ * sufficently new version of the X Render extension.
+ *
+ * Returns: a new #GdkCursor.
+ *
+ * Since: 3.10
+ */
+GdkCursor *
+gdk_cursor_new_from_surface (GdkDisplay *display,
+                            cairo_surface_t *surface,
+                            gdouble     x,
+                            gdouble     y)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (surface != NULL, NULL);
+  g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
+  g_return_val_if_fail (0 <= x && x < cairo_image_surface_get_width (surface), NULL);
+  g_return_val_if_fail (0 <= y && y < cairo_image_surface_get_height (surface), NULL);
+
+  return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display,
+                                                                 surface, x, y);
+}
 /**
  * gdk_cursor_get_display:
  * @cursor: a #GdkCursor.
@@ -405,7 +475,7 @@ gdk_cursor_get_image (GdkCursor *cursor)
   surface = gdk_cursor_get_surface (cursor, &x_hot, &y_hot);
   if (surface == NULL)
     return NULL;
+
   w = cairo_image_surface_get_width (surface);
   h = cairo_image_surface_get_height (surface);
 
index 50880b3e66a096ef9644df4c3cb9989b8d290f78..af843605a34e5f9628457131fd11da633d765bbf 100644 (file)
@@ -228,6 +228,11 @@ GdkCursor* gdk_cursor_new_from_pixbuf       (GdkDisplay      *display,
                                          GdkPixbuf       *pixbuf,
                                          gint             x,
                                          gint             y);
+GDK_AVAILABLE_IN_3_10
+GdkCursor* gdk_cursor_new_from_surface  (GdkDisplay      *display,
+                                         cairo_surface_t *surface,
+                                         gdouble          x,
+                                         gdouble          y);
 GDK_AVAILABLE_IN_ALL
 GdkCursor*  gdk_cursor_new_from_name    (GdkDisplay      *display,
                                          const gchar     *name);
index 582c2791d6af9d83e2d00b5ee61d50c910447303..365b429c33a03799777e1a7e70533c38b09f3775 100644 (file)
@@ -170,10 +170,10 @@ struct _GdkDisplayClass
                                                          GdkCursorType  type);
   GdkCursor *                (*get_cursor_for_name)     (GdkDisplay    *display,
                                                          const gchar   *name);
-  GdkCursor *                (*get_cursor_for_pixbuf)   (GdkDisplay    *display,
-                                                         GdkPixbuf     *pixbuf,
-                                                         gint           x,
-                                                         gint           y);
+  GdkCursor *                (*get_cursor_for_surface)  (GdkDisplay    *display,
+                                                         cairo_surface_t *surface,
+                                                         gdouble          x,
+                                                         gdouble          y);
 
   GList *                    (*list_devices)       (GdkDisplay *display);
   GdkAppLaunchContext *      (*get_app_launch_context) (GdkDisplay *display);
index 035106fd6d39933cdfce9ab74bba74d5c06317f3..76d0fbdf12ef6287fb9d267b787c122893a8538c 100644 (file)
@@ -55,9 +55,9 @@ struct _GdkWaylandCursor
   struct
   {
     int hotspot_x, hotspot_y;
-    int width, height;
+    int width, height, scale;
     struct wl_buffer *buffer;
-  } pixbuf;
+  } surface;
 
   struct wl_cursor *wl_cursor;
 };
@@ -168,8 +168,8 @@ gdk_wayland_cursor_finalize (GObject *object)
   GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object);
 
   g_free (cursor->name);
-  if (cursor->pixbuf.buffer)
-    wl_buffer_destroy (cursor->pixbuf.buffer);
+  if (cursor->surface.buffer)
+    wl_buffer_destroy (cursor->surface.buffer);
 
   G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
 }
@@ -188,7 +188,8 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
                                 int       *hotspot_x,
                                 int       *hotspot_y,
                                 int       *w,
-                                int       *h)
+                                int       *h,
+                               int       *scale)
 {
   GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor);
 
@@ -211,18 +212,20 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
 
       *w = image->width;
       *h = image->height;
+      *scale = 1;
 
       return wl_cursor_image_get_buffer (image);
     }
-  else /* From pixbuf */
+  else /* From surface */
     {
-      *hotspot_x = wayland_cursor->pixbuf.hotspot_x;
-      *hotspot_y = wayland_cursor->pixbuf.hotspot_y;
+      *hotspot_x = wayland_cursor->surface.hotspot_x;
+      *hotspot_y = wayland_cursor->surface.hotspot_y;
 
-      *w = wayland_cursor->pixbuf.width;
-      *h = wayland_cursor->pixbuf.height;
+      *w = wayland_cursor->surface.width / wayland_cursor->surface.scale;
+      *h = wayland_cursor->surface.height / wayland_cursor->surface.scale;
+      *scale = wayland_cursor->surface.scale;
 
-      return wayland_cursor->pixbuf.buffer;
+      return wayland_cursor->surface.buffer;
     }
 }
 
@@ -268,60 +271,6 @@ _gdk_wayland_cursor_init (GdkWaylandCursor *cursor)
 {
 }
 
-/* Used to implement from_pixbuf below */
-static void
-set_pixbuf (gpointer argb_pixels, int width, int height, GdkPixbuf *pixbuf)
-{
-  int stride, i, n_channels;
-  unsigned char *pixels, *end, *s, *d;
-
-  stride = gdk_pixbuf_get_rowstride(pixbuf);
-  pixels = gdk_pixbuf_get_pixels(pixbuf);
-  n_channels = gdk_pixbuf_get_n_channels(pixbuf);
-
-#define MULT(_d,c,a,t) \
-       do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
-
-  if (n_channels == 4)
-    {
-      for (i = 0; i < height; i++)
-       {
-         s = pixels + i * stride;
-          end = s + width * 4;
-          d = argb_pixels + i * width * 4;
-         while (s < end)
-           {
-             unsigned int t;
-
-             MULT(d[0], s[2], s[3], t);
-             MULT(d[1], s[1], s[3], t);
-             MULT(d[2], s[0], s[3], t);
-             d[3] = s[3];
-             s += 4;
-             d += 4;
-           }
-       }
-    }
-  else if (n_channels == 3)
-    {
-      for (i = 0; i < height; i++)
-       {
-         s = pixels + i * stride;
-          end = s + width * 3;
-          d = argb_pixels + i * width * 4;
-         while (s < end)
-           {
-             d[0] = s[2];
-             d[1] = s[1];
-             d[2] = s[0];
-             d[3] = 0xff;
-             s += 3;
-             d += 4;
-           }
-       }
-    }
-}
-
 GdkCursor *
 _gdk_wayland_display_get_cursor_for_type (GdkDisplay    *display,
                                          GdkCursorType  cursor_type)
@@ -382,10 +331,10 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay  *display,
 }
 
 GdkCursor *
-_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                           GdkPixbuf  *pixbuf,
-                                           gint        x,
-                                           gint        y)
+_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
+                                            cairo_surface_t *surface,
+                                            gdouble     x,
+                                            gdouble     y)
 {
   GdkWaylandCursor *cursor;
   GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
@@ -393,11 +342,8 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
   size_t size;
   gpointer data;
   struct wl_shm_pool *pool;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
-  g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
-  g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
+  cairo_surface_t *buffer_surface;
+  cairo_t *cr;
 
   cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
                         "cursor-type", GDK_CURSOR_IS_PIXMAP,
@@ -405,35 +351,55 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
                         NULL);
   cursor->name = NULL;
   cursor->serial = theme_serial;
-  cursor->pixbuf.hotspot_x = x;
-  cursor->pixbuf.hotspot_y = y;
+  cursor->surface.hotspot_x = x;
+  cursor->surface.hotspot_y = y;
 
-  if (pixbuf)
+  cursor->surface.scale = 1;
+
+  if (surface)
     {
-      cursor->pixbuf.width = gdk_pixbuf_get_width (pixbuf);
-      cursor->pixbuf.height = gdk_pixbuf_get_height (pixbuf);
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+       {
+         double sx, sy;
+         cairo_surface_get_device_scale (surface, &sx, &sy);
+         cursor->surface.scale = (int)sx;
+       }
+#endif
+      cursor->surface.width = cairo_image_surface_get_width (surface);
+      cursor->surface.height = cairo_image_surface_get_height (surface);
     }
   else
     {
-      cursor->pixbuf.width = 1;
-      cursor->pixbuf.height = 1;
+      cursor->surface.width = 1;
+      cursor->surface.height = 1;
     }
 
   pool = _create_shm_pool (wayland_display->shm,
-                           cursor->pixbuf.width,
-                           cursor->pixbuf.height,
+                           cursor->surface.width,
+                           cursor->surface.height,
                            &size,
                            &data);
 
-  if (pixbuf)
-    set_pixbuf (data, cursor->pixbuf.width, cursor->pixbuf.height, pixbuf);
+  if (surface)
+    {
+      buffer_surface = cairo_image_surface_create_for_data (data,
+                                                           CAIRO_FORMAT_ARGB32,
+                                                           cursor->surface.width,
+                                                           cursor->surface.height,
+                                                           cursor->surface.width * 4);
+      cr = cairo_create (buffer_surface);
+      cairo_set_source_surface (cr, surface, 0, 0);
+      cairo_paint (cr);
+      cairo_destroy (cr);
+      cairo_surface_destroy (buffer_surface);
+    }
   else
     memset (data, 0, 4);
 
-  stride = cursor->pixbuf.width * 4;
-  cursor->pixbuf.buffer = wl_shm_pool_create_buffer (pool, 0,
-                                                     cursor->pixbuf.width,
-                                                     cursor->pixbuf.height,
+  stride = cursor->surface.width * 4;
+  cursor->surface.buffer = wl_shm_pool_create_buffer (pool, 0,
+                                                     cursor->surface.width,
+                                                     cursor->surface.height,
                                                      stride,
                                                      WL_SHM_FORMAT_ARGB8888);
 
index 61cf9bc58c261584a6ac53d64d73a05923358dcd..6027e8d1b96fa5d5796123cf2c25d43316e47d77 100644 (file)
@@ -161,16 +161,17 @@ static gboolean
 gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
 {
   struct wl_buffer *buffer;
-  int x, y, w, h;
+  int x, y, w, h, scale;
   guint next_image_index, next_image_delay;
 
   buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index,
-                                           &x, &y, &w, &h);
+                                           &x, &y, &w, &h, &scale);
   wl_pointer_set_cursor (wd->wl_pointer,
                          wd->enter_serial,
                          wd->pointer_surface,
                          x, y);
   wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
+  wl_surface_set_buffer_scale (wd->pointer_surface, scale);
   wl_surface_damage (wd->pointer_surface,  0, 0, w, h);
   wl_surface_commit (wd->pointer_surface);
 
index 7d748e05a2673ab3196d3ea4acc66a50d64cfe70..db47bfe0ccb1194379e1e63a0cc64d23f66cd5f5 100644 (file)
@@ -587,7 +587,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
   display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size;
   display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type;
   display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name;
-  display_class->get_cursor_for_pixbuf = _gdk_wayland_display_get_cursor_for_pixbuf;
+  display_class->get_cursor_for_surface = _gdk_wayland_display_get_cursor_for_surface;
   display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha;
   display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color;
   display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates;
index ebe4f43bd4c88b3d600c797a43dbe0bc8013d1fd..e0d48d370d1ded21f8c0a8b7bde85bcb8feb65a4 100644 (file)
@@ -63,10 +63,10 @@ GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay    *display,
                                                     GdkCursorType  cursor_type);
 GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay  *display,
                                                     const gchar *name);
-GdkCursor *_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                                      GdkPixbuf  *pixbuf,
-                                                      gint        x,
-                                                      gint        y);
+GdkCursor *_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
+                                                       cairo_surface_t *surface,
+                                                       gdouble     x,
+                                                       gdouble     y);
 void       _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display,
                                                         guint       *width,
                                                         guint       *height);
@@ -81,7 +81,8 @@ struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
                                                   int       *hotspot_x,
                                                   int       *hotspot_y,
                                                   int       *w,
-                                                  int       *h);
+                                                  int       *h,
+                                                 int       *scale);
 guint      _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
                                                      guint      current_image_index,
                                                      guint     *next_image_delay);
index 507ec4258b6f09d94ae29578edaa3d0246bec8c1..e0c9f15112c50fabd3c0444aa3b2fb818e1f4204 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 #include <string.h>
 #include <errno.h>
+#include <math.h>
 
 struct _GdkX11Cursor
 {
@@ -514,23 +515,46 @@ _gdk_x11_cursor_update_theme (GdkCursor *cursor)
 
 #ifdef HAVE_XCURSOR
 
+static void
+get_surface_size (cairo_surface_t *surface,
+                 int *width,
+                 int *height)
+{
+  double x_scale, y_scale;
+
+  x_scale = y_scale = 1;
+
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+  cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
+#endif
+
+  /* Assume any set scaling is icon scale */
+  *width =
+    ceil (cairo_image_surface_get_width (surface) / x_scale);
+  *height =
+    ceil (cairo_image_surface_get_height (surface) / y_scale);
+}
+
 static XcursorImage*
-create_cursor_image (GdkPixbuf *pixbuf,
+create_cursor_image (cairo_surface_t *source_surface,
                      gint       x,
-                     gint       y)
+                     gint       y,
+                    gint       scale)
 {
-  guint width, height;
+  gint width, height;
   XcursorImage *xcimage;
   cairo_surface_t *surface;
   cairo_t *cr;
 
-  width = gdk_pixbuf_get_width (pixbuf);
-  height = gdk_pixbuf_get_height (pixbuf);
+  get_surface_size (source_surface, &width, &height);
 
+  width *= scale;
+  height *= scale;
+  
   xcimage = XcursorImageCreate (width, height);
 
-  xcimage->xhot = x;
-  xcimage->yhot = y;
+  xcimage->xhot = x * scale;
+  xcimage->yhot = y * scale;
 
   surface = cairo_image_surface_create_for_data ((guchar *) xcimage->pixels,
                                                  CAIRO_FORMAT_ARGB32,
@@ -538,53 +562,30 @@ create_cursor_image (GdkPixbuf *pixbuf,
                                                  height,
                                                  width * 4);
 
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+  cairo_surface_set_device_scale (surface, scale, scale);
+#endif
+
   cr = cairo_create (surface);
   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-  gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+  cairo_set_source_surface (cr, source_surface, 0, 0);
   cairo_paint (cr);
   cairo_destroy (cr);
-
   cairo_surface_destroy (surface);
 
   return xcimage;
 }
 
 GdkCursor *
-_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                        GdkPixbuf  *pixbuf,
-                                        gint        x,
-                                        gint        y)
+_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
+                                        cairo_surface_t *surface,
+                                        gdouble     x,
+                                        gdouble     y)
 {
   XcursorImage *xcimage;
   Cursor xcursor;
   GdkX11Cursor *private;
-  const char *option;
-  char *end;
-  gint64 value;
-
-  if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot")))
-    {
-      errno = 0;
-      end = NULL;
-      value = g_ascii_strtoll (option, &end, 10);
-      if (errno == 0 &&
-          end != option &&
-          value >= 0 && value < G_MAXINT)
-        x = (gint) value;
-    }
-  if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot")))
-    {
-      errno = 0;
-      end = NULL;
-      value = g_ascii_strtoll (option, &end, 10);
-      if (errno == 0 &&
-          end != option &&
-          value >= 0 && value < G_MAXINT)
-        y = (gint) value;
-    }
-
-  g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
-  g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
+  int target_scale;
 
   if (gdk_display_is_closed (display))
     {
@@ -592,7 +593,9 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
     }
   else
     {
-      xcimage = create_cursor_image (pixbuf, x, y);
+      target_scale =
+       gdk_screen_get_monitor_scale_factor (gdk_display_get_default_screen (display), 0);
+      xcimage = create_cursor_image (surface, x, y, target_scale);
       xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage);
       XcursorImageDestroy (xcimage);
     }
@@ -714,10 +717,10 @@ gdk_cursor_new_from_pixmap (GdkDisplay     *display,
 }
 
 GdkCursor *
-_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
-                                        GdkPixbuf  *pixbuf,
-                                        gint        x,
-                                        gint        y)
+_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display,
+                                        cairo_surface_t *surface,
+                                        gdouble     x,
+                                        gdouble     y)
 {
   GdkCursor *cursor;
   cairo_surface_t *pixmap, *mask;
@@ -728,13 +731,18 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
   GdkScreen *screen;
   cairo_surface_t *image;
   cairo_t *cr;
+  GdkPixbuf *pixbuf;
 
-  width = gdk_pixbuf_get_width (pixbuf);
-  height = gdk_pixbuf_get_height (pixbuf);
+  width = cairo_image_surface_get_width (surface);
+  height = cairo_image_surface_get_height (surface);
 
   g_return_val_if_fail (0 <= x && x < width, NULL);
   g_return_val_if_fail (0 <= y && y < height, NULL);
 
+  /* Note: This does not support scaled surfaced, if you need that you
+     want XCursor anyway */
+  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
+  
   n_channels = gdk_pixbuf_get_n_channels (pixbuf);
   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
   pixels = gdk_pixbuf_get_pixels (pixbuf);
@@ -766,6 +774,8 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
         }
     }
 
+  g_object_unref (pixbuf);
+
   screen = gdk_display_get_default_screen (display);
 
   pixmap = _gdk_x11_window_create_bitmap_surface (gdk_screen_get_root_window (screen),
@@ -798,7 +808,7 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display,
 
   cairo_surface_destroy (pixmap);
   cairo_surface_destroy (mask);
-
+  
   g_free (data);
   g_free (mask_data);
 
index 6f56e21ab62df7ea0c1b47dc478a030f961cbd97..575a3b7b03034f0a2649ce09d5c719574522ca6c 100644 (file)
@@ -2825,7 +2825,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
   display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
   display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type;
   display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
-  display_class->get_cursor_for_pixbuf = _gdk_x11_display_get_cursor_for_pixbuf;
+  display_class->get_cursor_for_surface = _gdk_x11_display_get_cursor_for_surface;
   display_class->get_default_cursor_size = _gdk_x11_display_get_default_cursor_size;
   display_class->get_maximal_cursor_size = _gdk_x11_display_get_maximal_cursor_size;
   display_class->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha;
index 57f7d89d4308c15d6bdbb99bf7585a6da19de2f0..543c42d0eadb17ffc4df18564c5d947d14b1d266 100644 (file)
@@ -259,10 +259,10 @@ GdkCursor *_gdk_x11_display_get_cursor_for_type     (GdkDisplay    *display,
                                                      GdkCursorType  type);
 GdkCursor *_gdk_x11_display_get_cursor_for_name     (GdkDisplay    *display,
                                                      const gchar   *name);
-GdkCursor *_gdk_x11_display_get_cursor_for_pixbuf   (GdkDisplay    *display,
-                                                     GdkPixbuf     *pixbuf,
-                                                     gint           x,
-                                                     gint           y);
+GdkCursor *_gdk_x11_display_get_cursor_for_surface  (GdkDisplay    *display,
+                                                     cairo_surface_t *surface,
+                                                     gdouble        x,
+                                                     gdouble        y);
 gboolean   _gdk_x11_display_supports_cursor_alpha   (GdkDisplay    *display);
 gboolean   _gdk_x11_display_supports_cursor_color   (GdkDisplay    *display);
 void       _gdk_x11_display_get_default_cursor_size (GdkDisplay *display,